package service

import (
	"context"

	"github.com/jinzhu/copier"
	"go.uber.org/zap"
	"golang-sgg-daijia/api/v1"
	"golang-sgg-daijia/internal/const/redisconst"
	"golang-sgg-daijia/internal/model"
	"golang-sgg-daijia/internal/repository/mysql"
	"golang-sgg-daijia/internal/repository/redis"
	"golang-sgg-daijia/internal/repository/wechat"
	"strconv"
	"time"
)

type CustomerInfoService interface {
	GetCustomerInfo(ctx context.Context, customerID int64) (*v1.CustomerLoginVo, error)
	Login(ctx context.Context, code string) (string, error)
	UpdateWxPhoneNumber(ctx context.Context, updateWxPhoneForm *v1.UpdateWxPhoneForm) (bool, error)
}

func NewCustomerInfoService(
	service *Service,
	customerInfoDao mysql.CustomerInfoDao,
	customerLoginLogDao mysql.CustomerLoginLogDao,
	wxclient wechat.WeChatMiniClient,
	redisCli redis.RedisClient,
	orderInfoDao mysql.OrderInfoDao,
	driverInfoDao mysql.DriverInfoDao,
) CustomerInfoService {
	return &customerInfoService{
		Service:             service,
		customerInfoDao:     customerInfoDao,
		customerLoginLogDao: customerLoginLogDao,
		wechat:              wxclient,
		rdb:                 redisCli,
		orderInfoDao:        orderInfoDao,
		driverInfoDao:       driverInfoDao,
	}
}

type customerInfoService struct {
	*Service
	customerInfoDao     mysql.CustomerInfoDao
	customerLoginLogDao mysql.CustomerLoginLogDao
	wechat              wechat.WeChatMiniClient
	rdb                 redis.RedisClient
	orderInfoDao        mysql.OrderInfoDao
	driverInfoDao       mysql.DriverInfoDao
}

func (s *customerInfoService) UpdateWxPhoneNumber(ctx context.Context, updateWxPhoneForm *v1.UpdateWxPhoneForm) (bool, error) {
	//phoneInfo, err := s.wechat.GetPhoneNoInfo(ctx, updateWxPhoneForm.Code)
	//if err != nil {
	//	return false, err
	//}
	customerInfo, err := s.customerInfoDao.GetById(ctx, updateWxPhoneForm.CustomerID)
	if err != nil {
		return false, err
	}
	//customerInfo.Phone = phoneInfo.PhoneNumber
	customerInfo.Phone = "1008611"
	err = s.customerInfoDao.Update(ctx, customerInfo)
	if err != nil {
		return false, err
	}
	return true, nil
}

func (s *customerInfoService) GetCustomerInfo(ctx context.Context, customerID int64) (*v1.CustomerLoginVo, error) {

	customerInfo, err := s.customerInfoDao.GetById(ctx, customerID)
	if err != nil {
		return nil, err
	}
	customerLoginVo := &v1.CustomerLoginVo{}
	err = copier.Copy(customerLoginVo, customerInfo)
	if err != nil {
		s.logger.WithContext(ctx).Error("customerInfo|GetCustomerInfo|Copy", zap.Error(err))
		return nil, err
	}
	if customerInfo.Phone != "" {
		customerLoginVo.IsBindPhone = true
	}
	return customerLoginVo, nil
}

// Login 微信小程序登录接口
func (s *customerInfoService) Login(ctx context.Context, code string) (string, error) {
	// 1.1 获取code值，使用微信工具包对象，获取微信唯一标识openid
	sessionInfo, err := s.wechat.GetSession(ctx, code)
	if err != nil {
		return "", err
	}
	openid := sessionInfo.OpenID
	// 1.2 根据openid查询数据库，判断是否第一次登录
	customerInfo, err := s.customerInfoDao.GetByOpenid(ctx, openid)
	if err != nil {
		return "", err
	}
	// 1.3 如果第一次登录，添加信息到用户表
	if customerInfo == nil {
		customerInfo = &model.CustomerInfo{
			Nickname:  strconv.FormatInt(time.Now().UnixMilli(), 10),
			WxOpenID:  openid,
			AvatarURL: "https://oss.aliyuncs.com/aliyun_id_photo_bucket/default_handsome.jpg",
		}
		err = s.customerInfoDao.Create(ctx, customerInfo)
		if err != nil {
			return "", err
		}
	}
	// 1.4 记录登录日志信息
	err = s.customerLoginLogDao.Create(ctx, &model.CustomerLoginLog{
		CustomerID: strconv.FormatInt(customerInfo.ID, 10),
		Msg:        "小程序登录",
	})
	if err != nil {
		return "", err
	}
	// 2 生成token字符串
	token, err := s.jwt.GenToken(strconv.FormatInt(customerInfo.ID, 10), time.Now().Add(time.Hour*24*90))
	if err != nil {
		s.logger.WithContext(ctx).Error("customerInfoService|Login|GenToken", zap.Any("data", map[string]interface{}{
			"customerID": customerInfo.ID,
		}), zap.Error(err))
		return "", err
	}
	// 3 把用户id放到redis，设置过期时间
	// key:token  value:customerId
	err = s.rdb.Set(ctx, redisconst.UserLoginKeyPrefix+token, customerInfo.ID, redisconst.UserLoginKeyTimeOut)
	return token, err
}
